/*++ Module: Expand Programming Assignment #2 CSE 373 2000 Winter Quarter University of Washington Description: This module demonstrates a lossless compression strategy loosely based on the LZRW and LZNT1 format. Author: Gary Kimura [GaryKi@cs.washington.edu] 12-Feb-2000 Revision History: --*/ #include // // Global variables // // // Declare the variables used to hold and describe the state of the input and // output buffers // unsigned char InputBuffer[50000]; int InputBufferLength; unsigned char OutputBuffer[50000]; int OutputBufferLength; // // The number of token we've already processed from the input buffer // int InputTokenCount; // // The index within the input buffer of the current control byte that we're // processing // int CurrentControlByteIndex; // // Local procedure prototypes for doing I/O // int ReadBuffer ( unsigned char *Buffer, int Limit ); void WriteBuffer ( unsigned char *Buffer, int Length ); // // Local procedures prototypes for processing tokens // void ProcessDataToken ( unsigned char Data ); void ProcessCopyToken ( unsigned char Offset, unsigned char Length ); void main( int argc, char *argv[] ) /*++ Routine Description: This is the main routine for expanding a compressed data file Arguments: argc - The number of command line arguments argv - The actual command line arguments Return Value: None. --*/ { int CurrentInputBufferIndex; int Length; int Offset; int i; // // Fix up standard input and output to be binary files // if (argc >= 2) { if (stdin != freopen( argv[1], "rb", stdin )) { fprintf(stderr, "Redirection of stdin error\n"); return; } } if (argc >= 3) { if (stdout != freopen( argv[2], "wb", stdout )) { fprintf(stderr, "Redirection of stdout error\n"); return; } } // // Read in input buffer, and set the input state // InputBufferLength = ReadBuffer( InputBuffer, 50000 ); InputTokenCount = 0; CurrentControlByteIndex = 0; // // Initialize the output control variable // OutputBufferLength = 0; // // To do the decompression we'll loop through the input buffer using // CurrentInputBufferIndex to control where we're at in the input // buffer and to decide when to terminate the loop // CurrentInputBufferIndex = 0; while (CurrentInputBufferIndex < InputBufferLength) { // // First check if we need to update ourselves to the next control // byte which is located at the next input index location // if ((InputTokenCount % 8) == 0) { CurrentControlByteIndex = CurrentInputBufferIndex; // // Update the index and check if we've exhausted the input buffer // CurrentInputBufferIndex += 1; if (CurrentInputBufferIndex >= InputBufferLength) { break; } } // // Decipher the next token // if (InputBuffer[CurrentControlByteIndex] & (1 << (InputTokenCount % 8))) { // // Copy token, grab its offset and length and then do the copy // Offset = InputBuffer[ CurrentInputBufferIndex ]; Length = InputBuffer[ CurrentInputBufferIndex + 1 ]; for (i = 0; i < Length; i += 1) { OutputBuffer[ OutputBufferLength + i ] = OutputBuffer[ OutputBufferLength + i - Offset]; } // // Update the output and input buffer information // OutputBufferLength += Length; CurrentInputBufferIndex += 2; } else { // // Data token, just emit the next byte // OutputBuffer[ OutputBufferLength ] = InputBuffer[ CurrentInputBufferIndex ]; // // Update the output and input buffer information // OutputBufferLength += 1; CurrentInputBufferIndex += 1; } // // Each time through this outer loop we've processed a token // InputTokenCount += 1; } // // Write out the output buffer // WriteBuffer( OutputBuffer, OutputBufferLength ); return; } int ReadBuffer ( unsigned char *Buffer, int Limit ) /*++ Routine Description: A simply routine to simply read in from stdin and fill the buffer up to the limit Arguments: Buffer - A pointer to the buffer we're to fill Limit - The maximum number of characters we can use in the buffer Return Value: int - The actual number of bytes read in --*/ { int c,i; // // Loop until we've exhausted the input or the limit // i = 0; while ((--Limit > 0) && ((c = getchar()) != EOF)) { Buffer[i++] = c; } // // And return the number of bytes we're read in // return i; } void WriteBuffer ( unsigned char *Buffer, int Length ) /*++ Routine Description: A simple routine to output a buffer to stdout Arguments: Buffer - Supplies a pointer to the buffer being output Length - Supplies the length, in bytes, of the output buffer Return Value: None. --*/ { int i; for (i = 0; i < Length; i += 1) { putchar(Buffer[i]); } return; }